package com.appspot.bambugame.server.data;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;

import javax.persistence.Id;

import com.googlecode.objectify.annotation.Cached;

@Cached
public class HangmanPlurkQuestion
{
    @Id public long PLURK_ID;
    public String SENTENCE;
    public String HINT;
    public Long TIMESTAMP;
    
    public Boolean IS_SOLVED;
//    public Boolean IS_HANGED;
    
    public int LIVES_TOTAL;
    public String GUESSED_CHARS;
    
    public String EXTRAS;
    
    public Integer LAST_RESPONSE_OFFSET;
    
    public HangmanPlurkQuestion()
    {
    }
    
    public HangmanPlurkQuestion(long pPlurkID, String pSentence, String pHint)
    {
        this(pPlurkID, pSentence, pHint, "");
    }
    
    public HangmanPlurkQuestion(long pPlurkID, String pSentence, String pHint, String pExtras)
    {
        PLURK_ID = pPlurkID;
        
        SENTENCE = pSentence;
        SENTENCE = SENTENCE.trim();
        while (SENTENCE.contains( "  " )) SENTENCE = SENTENCE.replace( "  ", " " );
        SENTENCE = SENTENCE.toLowerCase();
        
        HINT = pHint;
        
        IS_SOLVED = Boolean.FALSE;
//        IS_HANGED = Boolean.FALSE;
        
        LIVES_TOTAL = 10;
        
        LAST_RESPONSE_OFFSET = 0;
        
        GUESSED_CHARS = "";
        
        EXTRAS = pExtras;
        
        TIMESTAMP = Calendar.getInstance(TimeZone.getTimeZone( "Europe/Amsterdam" )).getTimeInMillis();
    }
    
    private Set<Character> getGuessedChars()
    {
        if (GUESSED_CHARS.length() == 0) return new HashSet<Character>();
        
        char[] tGuessedCharArray = GUESSED_CHARS.toCharArray();
        Set<Character> tReturnSet = new HashSet<Character>();
        
        for (Character tChar : tGuessedCharArray)
        {
            if (Character.isLetterOrDigit( tChar )) tReturnSet.add( tChar );
        }
        
        return tReturnSet;
    }
    
    public boolean hasQuestionBeenHanged()
    {
        return getLivesRemaining() == 0;
    }
    
    public static List<Character> cSpeciallyAcceptedChars = new ArrayList<Character>(Arrays.asList( new Character[]{'&', '\'', '-', ':', ',', '(', ')'} ) );
    
//    public static String getSpecialCharactersString()
//    {
//        StringBuilder tBuilder = new StringBuilder();
//        
//        for (char tChar : cSpeciallyAcceptedChars)
//        {
//            if (tBuilder.length() > 0) tBuilder.append( ',' );
//        }
//    }
    
    public boolean hasQuestionBeenGuessed()
    {
        if (IS_SOLVED) return true;
        
        String tCopiedSentence = new String( SENTENCE );
        
        // special handling for cSpeciallyAcceptedChars
        for (char tChar : cSpeciallyAcceptedChars)
        {
            tCopiedSentence = tCopiedSentence.replace( tChar, ' ' );
        }
        
        for ( Character tCheckedCharacter : getGuessedChars() )
        {
            tCopiedSentence = tCopiedSentence.replace( tCheckedCharacter, ' ' );
        }
        
        return tCopiedSentence.trim().isEmpty();
    }
    
    public int getLivesRemaining()
    {
        int tRemaining = LIVES_TOTAL;
        for( Character tCheckedCharacter : getGuessedChars() )
        {
            if (!SENTENCE.contains( "" + tCheckedCharacter ))
            {
                tRemaining--;
            }
        }
        
        if (tRemaining < 0) tRemaining = 0;
        
        return tRemaining;
    }

    public int getLivesRemainingInPercent()
    {
        if (IS_SOLVED) return 110;
        return Math.round( ( ( (float) getLivesRemaining() / (float) LIVES_TOTAL) * 10) ) * 10;
    }
    
    public void addGuessedCharacter(Character pGuessedCharacter)
    {
        //getGuessedChars().add( Character.toLowerCase( pGuessedCharacter ) );
        GUESSED_CHARS = GUESSED_CHARS + pGuessedCharacter;
    }
    
    public boolean hasCharacterBeenGuessed(Character pGuessedCharacter)
    {
        pGuessedCharacter = Character.toLowerCase( pGuessedCharacter );
        return GUESSED_CHARS.contains( "" + pGuessedCharacter );
    }

    public boolean isGuessCharacterCorrect( Character pPlurkerGuessCharacter )
    {
        return SENTENCE.contains( "" + pPlurkerGuessCharacter );
    }
    
    public boolean isGuessStringCorrect( String pPlurkerGuessString )
    {
        pPlurkerGuessString = pPlurkerGuessString.trim().toLowerCase();
        
        // remove double white spaces
        while (pPlurkerGuessString.contains( "  " )) pPlurkerGuessString = pPlurkerGuessString.replace( "  ", " " );
        
        String[] tPlurkerGuessStringArray = pPlurkerGuessString.split( " " );
        String[] tQuestionSentenceStringArray = SENTENCE.split( " " );
        
        if (tPlurkerGuessStringArray.length != tQuestionSentenceStringArray.length) return false;
        
        //for (String tPlurkerGuessString : tPlurkerGuessStringArray)
        for (int i = 0; i < tPlurkerGuessStringArray.length; i++)
        {
            if (!tPlurkerGuessStringArray[i].equalsIgnoreCase( tQuestionSentenceStringArray[i] )) return false;
        }
        
        return true;
    }
    
    public String toString()
    {
        return "[" + PLURK_ID + "|" + SENTENCE + "]";
    }

    public int getNumberOfWords()
    {
        int tNumOfWords = 0;
        boolean tIsAtWhitespace = true;
        
        for (int i = 0; i < SENTENCE.length(); i++)
        {
            if (!Character.isWhitespace( SENTENCE.charAt( i ) ))
            {
                if (tIsAtWhitespace)
                {
                    tIsAtWhitespace = false;
                    tNumOfWords++;
                }
            }
            else
            {
                tIsAtWhitespace = true;
            }
        }
        
        return tNumOfWords;
    }
}
